package com.huawei.codearts.controller;

import com.huawei.codearts.model.User;
import com.huawei.codearts.service.AsyncService;
import com.huawei.codearts.tools.exception.ExceptionUtil;
import com.huawei.codearts.tools.ratelimit.annotation.LimitType;
import com.huawei.codearts.tools.ratelimit.annotation.RateLimit;
import com.huawei.codearts.tools.exception.CustomException;
import com.huawei.codearts.tools.ratelimit.annotation.RateLimitCustom;
import com.huawei.codearts.tools.ratelimit.annotation.RateLimiter;
import com.huawei.codearts.tools.ratelimit.service.RedisLuaLimiter;
import com.huawei.codearts.tools.utils.ResultResponse;
import com.huawei.codearts.tools.utils.ResultUtils;
import com.huawei.codearts.tools.validated.StatusEnum;
import com.huawei.codearts.tools.validated.ValidParams;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

@RestController
//@ApiVersion(value = 0)
//@RequestMapping(value = {"api/test", "api/{}/test"})
@RequestMapping(value = {"api/test", "api/*/test"})
public class TestController {

    private final RedisLuaLimiter redisLuaLimiter;
    private final AsyncService asyncService;

    @Autowired
    public TestController(AsyncService asyncService, RedisLuaLimiter redisLuaLimiter) {
        this.asyncService = asyncService;
        this.redisLuaLimiter = redisLuaLimiter;
    }

    @RequestMapping
    public ResultResponse<String> index(@RequestParam Map<String, Object> params,
                                        @RequestParam Long id) {
        System.out.println(params);
        System.out.println(params.get("id"));
//        int i= 1 / 0;  // 测试异常状态补捕获 通过 AOP @Around 做的捕获
        return ResultUtils.success("hello world");
//        return ResultUtils.error(StatusEnum.UNAUTHORIZED);
    }

    @RequestMapping(value = "/sign/{id}")
    public ResultResponse<String> sign(@PathVariable Long id, @RequestBody User user) {
        return ResultUtils.success("hello sign");
    }

    @RequestMapping({"/error"})
    public void error() {
        /** 四种形式抛出异常 */
//        throw new ServiceException(StatusEnum.UNAUTHORIZED);
//        throw new ServiceException(StatusEnum.ERROR, "用户名已存在");
//        throw new CustomException("密码错误");
//        throw new CustomException(1101, "密码错误");

        /** 工具类方式 */
//        ExceptionUtil.rethrowServiceException(StatusEnum.UNAUTHORIZED);
//        ExceptionUtil.rethrowServiceException(StatusEnum.ERROR, "用户名已存在");
//        ExceptionUtil.rethrowCustomException("密码错误");
        ExceptionUtil.rethrowCustomException(1101, "密码错误");
    }

//    @RequestMapping(value = {"/home"},
//            method = RequestMethod.GET,
//            params = {"username", "password!=123456"})  // 必须仍带 username和password 参数
//    @RequestMapping("/testRest/{id}/{username}")
//    public String testRest(@PathVariable("id") String id, @PathVariable("username") String username) {
    @RequestMapping(value = {"/home"})
    public ResultResponse<String> home() {
        return ResultUtils.success("v0 hello home");
    }

    @RequestMapping(value = "/start-task")
    public String startTask() throws InterruptedException {
        asyncService.executeTask();  // 异步执行无需等待
        return "Task started";  // 直接返回
    }

    /**
     * 限流测试 令牌桶算法
     * 基于 RateLimiter 实现
     */
    @RequestMapping(value = "/send")
    @RateLimit(value = 1.0/10.0)  // 限流 1.0 表示每秒访问一次, 1.0/60.0 表示每分钟访问一次
    public ResultResponse<String> send(String message) {
        return ResultUtils.success("hello send");
    }

    /**
     * 限流测试 令牌桶算法
     * 自定义 AtomicInteger 实现
     */
    @RequestMapping(value = "/atom")
    @RateLimitCustom(maxTokens = 10, refillRate = 5)
    public ResultResponse<String> atomicInteger(String message) {
        return ResultUtils.success("hello atom");
    }

    /**
     * 限流测试 计数器算法
     * 基于 Redis Lua 脚本实现
     * 根据key限流  [默认根据方法限流 如果使自定义key生效需要设置：limitType = LimitType.Custom]
     */
    @RequestMapping(value = "/rate/limiter/hello")
    @RateLimiter(limitType = LimitType.CUSTOM, key = "#{key}", time = 10, count = 3)  // 限流 10 秒之内，这个接口可以访问3次
    public ResultResponse<String> hello(@RequestParam("key") String key) {
        return ResultUtils.success("hello word");
    }

    /**
     * 限流测试 计数器算法
     * 基于 Redis Lua 脚本实现
     * 根据手机号限流
     */
    @RequestMapping(value = "/rate/limiter/phone")
    @RateLimiter(limitType = LimitType.CUSTOM, key = "#{param.phone}", time = 10, count = 1)  // 限流 10 秒之内，这个接口可以访问1次
    public ResultResponse<String> phone(@RequestParam Map<String, Object> param) {
        return ResultUtils.success("hello phone");
    }

    /**
     * 限流测试 计数器算法
     * 基于 Redis Lua 脚本实现
     * 根据uid限流
     */
    @RequestMapping(value = "/rate/limiter/uid")
    @RateLimiter(limitType = LimitType.USER, time = 10, count = 2)  // 限流 10 秒之内，这个接口可以访问2次
    public ResultResponse<String> uid() {
        return ResultUtils.success("hello uid");
    }

    /**
     * 自定义逻辑限流 & 幂等设计（防止重复请求）
     */
    @RequestMapping(value = "/rate/limiter/custom")
    public ResultResponse<String> custom(@RequestHeader("Request-Key") String requestKey) {

        // 检查是否为重复请求
        if (redisLuaLimiter.isDuplicateRequest(requestKey)) {
            return ResultUtils.error("Duplicate Request");
        }

        // 检查是否超出限流
        if (redisLuaLimiter.tryAcquire(requestKey, 1, 10)) {
            return ResultUtils.error("Too Many Requests");
        }
        return ResultUtils.success("hello custom");
    }

    /**
     * 参数验证（Hibernate Validator） 自定义效验器
     */
    @Validated
    @RequestMapping(value = "/validator")
    public ResultResponse<String> validator(@Valid @ValidParams @RequestParam Map<String, Object> params) {
        return ResultUtils.success("retrieved successfully!");
    }
}
